<?php


namespace Modules\Admin\Services;


use App\Services\BaseService;
use Illuminate\Routing\Route;
use Illuminate\Support\Arr;
use Overtrue\LaravelPinyin\Facades\Pinyin;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Modules\Admin\Entities\Permission;
use Nwidart\Modules\Facades\Module;

class PermissionService extends BaseService
{
    /**
     * 说明：如果不是超级管理员 移除树中当前用户没有的权限【当子管理员拥有分配权限的权限时 只能分配自己拥有的权限】
     *
     * @return
     * @param   type
     * @author  daixinguo (daixinguo57@163.com)
     */
    public function getMyPermissionsByTree($permissions, $admin)
    {
        if ($admin->super_admin) {
            return $permissions;
        }
        foreach ($permissions as $key => &$value) {
            if (!$admin->hasAllPermissions($value['name'])) {
                unset($permissions[$key]);
            }
            if (is_array($permissions)) {
                $permissions = array_values($permissions);
            }
            if (!empty($value['children']) && count($value['children']) > 0) {
                $value['children'] = $this->getMyPermissionsByTree($value['children'], $admin);
            }
        }
        unset($value);

        return $permissions;
    }

    /**
     * 说明：通过获取所有路由刷新权限表【通过laravel-permission自带的方法进行添加这样可以沿用扩展的缓存机制】
     *
     * @return
     * @param   sting|null $search_alias 搜索路由
     * @author  daixinguo (daixinguo57@163.com)
     */
    public function refreshPermissionByRoute(Router $router, $guard_name = 'admin', $search_alias = null)
    {
        $routes = collect($router->getRoutes())->flatMap(function ($route) use ($search_alias) {
            if ($route->checkPermission()) {
                return $this->getRouteInformation($route, $search_alias);
            }
        })->unique('permission_name')->values()->all();
        $this->savePermissions($routes, $guard_name);
        Cache::forget('spatie.permission.cache');
        return $routes;
    }

    /**
     * 说明：删除权限
     *
     * @return
     * @param   sting|null $search_alias 搜索路由 搜索时 右模糊  {$search_alias}%
     * @author  daixinguo (daixinguo57@163.com)
     */
    public function delPermission($guard_name = "all", $search_alias = null)
    {
        if ($guard_name == 'all') {
            $guard_name = ['admin', 'user'];
        } else {
            $guard_name = [$guard_name];
        }

        if (!is_null($search_alias)) {
            $del_count = Permission::query()->whereIn("guard_name", $guard_name)->where("description", "like", "{$search_alias}%")->delete();
        } else {
            $del_count = Permission::query()->whereIn("guard_name", $guard_name)->delete();
        }

        if ($del_count) {
            Cache::forget('spatie.permission.cache');
            Permission::fixTree();
        }
        return $del_count;
    }

    /**
     * 说明：将权限路由写入permissions表
     *
     * @return
     * @param   type
     * @author  daixinguo (daixinguo57@163.com)
     */
    public function savePermissions($permission_routes, $guard_name)
    {
        foreach ($permission_routes as $key => $value) {
            $menu = false;
            $page_name = null;
            $sort = 0;
            if ($value['description'] == '权限管理') {
                $menu = true;
                $page_name = 'Permissions';
                $sort = 1000;
            }
            if ($value['description'] == '权限管理.权限列表') {
                $menu = true;
                $page_name = 'List';
                $sort = 10;
            }
            $permission = Permission::updateOrCreate(
                ['name' => $value['permission_name'], 'guard_name' => $guard_name],
                [
                    'name' => $value['permission_name'],
                    'guard_name' => $guard_name,
                    'title' => $value['title'],
                    'index' => $value['index'],
                    'menu' => $menu,
                    'page_name' => $page_name,
                    'sort' => $sort,
                    'description' => $value['description'],
                ],
            );
            if (!is_null($value['parent'])) {
                $parent_id = Permission::query()->where('name', $value['parent'])->where('guard_name', $guard_name)->value('id');
                // 借助父节点属性 【这样写才能正确维护 _lft _rgt】
                $permission->parent_id = $parent_id;
                $permission->save();
            }
        }
    }

    /**
     * 获取路由信息 【获取扩展路由方法配置的路由权限信息】
     *
     * @param \Illuminate\Routing\Route $route
     * @param string|null $alias 模糊查找指定的路由  右模糊匹配
     *
     * @return array
     */
    public function getRouteInformation(Route $route, $search_alias = null)
    {
        $permissions = [];
        $alias = $route->getAlias();
        if (!is_null($search_alias) && !Str::startsWith($alias, $search_alias)) {
            return $permissions;
        }
        $alias_arr = explode(".", $alias);
        $title = last($alias_arr);
        foreach ($alias_arr as $key => $value) {
            $parent = isset($parent_arr_pinyin) ? implode(".", $parent_arr_pinyin) : null;
            $parent_arr_pinyin[] = Pinyin::sentence($value);
            $all_parent_pinyin = implode(".", $parent_arr_pinyin);
            $parent_arr[] = $value;
            $all_parent = implode(".", $parent_arr);
            if ($value == $title) {
                $permissions[] = [
                    'parent' => $parent,
                    'title' => $value,
                    'permission_name' => $route->getPermissionName(),
                    'index' => $route->checkIndex(),
                    'description' => $all_parent,
                    'deep' => $key + 1
                ];
            } else {
                $permissions[] = [
                    'parent' => $parent,
                    'title' => $value,
                    'permission_name' => $all_parent_pinyin,
                    'index' => false,
                    'description' => $all_parent,
                    'deep' => $key + 1
                ];
            }
        }
        $permissions = array_values(Arr::sort($permissions, function ($value) {
            return $value['deep'];
        }));
        return $permissions;
    }

    /**
     * 说明：获取所有权限
     *
     * @return
     * @param   type
     * @author  daixinguo (daixinguo57@163.com)
     */
    public static function getAllPermissions()
    {
        $permissions = Cache::get("permissions");
        if (is_null($permissions)) {
            $permissions = Permission::all()->toArray();
            Cache::put('permissions', $permissions);
        }
        return $permissions;
    }

    /**
     * 说明：将每个权限的祖先都找出来 【前端添加权限时当一个菜单下只选择了其中几个权限时，父级菜单不会选中，导致获取菜单不全，添加权限时自动将权限的祖先加进去，这些祖先往往可能是菜单】
     *
     * @return  array $permission_ancestors  每个权限的祖先 [['权限id' => ['祖先id','祖先id']]]
     * @param
     * @author  daixinguo (daixinguo57@163.com)
     * php artisan tinker --execute "Modules\Core\Services\RolePermission\PermissionService::getPermissionAncestors();"
     */
    public static function getPermissionAncestors()
    {
        $permission_ancestors = Cache::get("permission_ancestors");
        if (is_null($permission_ancestors)) {
            $permissions = self::getAllPermissions();
            $permissions = collect($permissions);
            $permission_ancestors = [];
            foreach ($permissions as $permission) {
                $ancestors = $permissions->where('_lft', '<', $permission['_lft'])->where('_rgt', '>', $permission['_rgt'])->pluck('id');
                if ($ancestors->isNotEmpty()) {
                    $permission_ancestors[$permission['id']] = $ancestors->toArray();
                }
            }
            Cache::put('permission_ancestors', $permission_ancestors);
        }

        return $permission_ancestors;
    }

    /**
     * 说明：将选中的权限与这些权限的祖先合并并去重
     *
     * @return
     * @param   type
     * @author  daixinguo (daixinguo57@163.com)
     * php artisan tinker --execute "Modules\Core\Services\RolePermission\PermissionService::mergePermissionAncestors([238,239,240]);"
     */
    public static function mergePermissionAncestors($permissions)
    {
        if (is_null($permissions) || empty($permissions)) {
            return $permissions;
        }
        $permission_ancestors = self::getPermissionAncestors();
        $ancestors = [];
        foreach ($permissions as $permission) {
            if (!empty($permission_ancestors[$permission])) {
                $ancestors = array_merge($ancestors, $permission_ancestors[$permission]);
            }
        }
        $new_permissions = array_merge($permissions, $ancestors);
        // 去重
        $new_permissions = array_values(array_unique($new_permissions));
        return $new_permissions;
    }
}
